#ifndef __M_EXCHANGE_H__
#define  __M_EXCHANGE_H__
#include "../mqcommon/logger.hpp"
#include "../mqcommon/sqliter.hpp"
#include "../mqcommon/spliter.hpp"
#include "../mqcommon/filer.hpp"
#include "../mqcommon/message.pb.h"
#include<google/protobuf/map.h>

/*
    1.实现交换机类
    2.实现交换机数据持久化管理类
    3.实现交换机数据内存管理类
*/
#include <iostream>
#include <unordered_map>
#include <string>
#include <mutex>
#include <memory>
#include <sstream>

namespace zhong
{
    // 交换机类
    struct Exchange
    {
        using ptr = std::shared_ptr<Exchange>; // ptr交换机对象的智能指针

        std::string _name;                                      // 交换机名称
        ExchangeType _type;                                     // 交换机类型
        bool _durable;                                          // 持久化标志
        bool _auto_delete;                                      // 是否自动删除
        // std::unordered_map<std::string, std::string> _args_map; // 其它参数
        google::protobuf::Map<std::string, std::string> _args_map;

        Exchange() {}
        Exchange(std::string name,
                 ExchangeType type,
                 bool durable,
                 bool auto_delete,
                 const google::protobuf::Map<std::string, std::string> &args_map)
            : _name(name), _type(type), _durable(durable), _auto_delete(auto_delete), _args_map(args_map) {}

        // _args_map存储兼职对视，在存储数据库时，会组织一个格式进行存储
        void setArgs(const std::string &args)
        {
            // 解析args字符串，将内容存储到map中
            // 格式：key=val&key=val
            std::vector<std::string> sub_args;
            Spliter::split(args, "&", sub_args);
            for (auto &e : sub_args)
            {
                size_t pos = e.find("=");
                std::string key = e.substr(0, pos);
                std::string value = e.substr(pos + 1);
                // _args_map.insert(std::make_pair(key, value));  // 当args类型为unordered_map
                _args_map[key] = value;
            }
        }
        // 将_args_map内容序列化后，返回一个字符串
        std::string getArgs()
        {
            std::string ret;
            for (auto &e : _args_map)
            {
                std::string part = e.first + "=" + e.second + "&";
                ret += part;
            }
            // ret.pop_back(); // 删除最后一个&
            return ret;
        }
    };

    // 交换机数据持久化管理类 --- 磁盘的交换机数据
    class ExchangeMapper
    {
    public:
        using ptr = std::shared_ptr<ExchangeMapper>;

        ExchangeMapper(const std::string &data_base_file)
            : _sqliter(data_base_file)
        {
            std::string path = Filer::parentDirectory(data_base_file); // 获取父级目录
            Filer::createDirectory(path);                              // 创建目录
            assert(_sqliter.open());                                   // 创建数据库
            createTable();
        }

        void createTable()
        {
            // 构造表的创建语句
            std::string sql_create = "create table if not exists exchange_table(name varchar(32) primary key,\
                                                                            type int, \
                                                                            durable int,\
                                                                            auto_delete int,\
                                                                            args varchar(128));";
            if (_sqliter.exec(sql_create, nullptr, nullptr) == false)
            {
                ERR_LOG("创建交换机数据库失败");
                abort(); // 退出程序
            }
        }
        void removeTable()
        {
            std::string sql_remove = "drop table if exists exchange_table";
            if (_sqliter.exec(sql_remove, nullptr, nullptr) == false)
            {
                ERR_LOG("删除交换机数据库失败");
                abort(); // 退出程序
            }
        }
        // // 插入交换机数据    // 存在bug
        // void insert(Exchange::ptr &exchange)
        // {
        //     std::string sql_insert = "insert into exchange_table values('%s',%d,%d,%d,'%s');";
        //     // 添加sql Insert内容
        //     char sql_str[4096] = {0};
        //     sprintf(sql_str, sql_insert.c_str(), exchange->_name.c_str(), exchange->_type, exchange->_durable, exchange->_auto_delete, exchange->getArgs().c_str());
        //     if (_sqliter.exec(sql_insert, nullptr, sql_str) == false)
        //     {
        //         INFO_LOG("添加交换机数据失败, 错误原因[%s]", strerror(errno));
        //         return; // 退出程序
        //     }
        // }
        bool insert(Exchange::ptr &exp)
        {
            std::stringstream ss;
            ss << "insert into exchange_table values(";
            ss << "'" << exp->_name << "', ";
            ss << exp->_type << ", ";
            ss << exp->_durable << ", ";
            ss << exp->_auto_delete << ", ";
            ss << "'" << exp->getArgs() << "');";
            if (_sqliter.exec(ss.str(), nullptr, nullptr) == false)
            {
                INFO_LOG("添加交换机数据失败, 错误原因[%s]", strerror(errno));
                return false; // 退出程序
            }
            return true;
        }
        // 移除交换机数据
        void remove(const std::string &exchane_name)
        {
            std::string sql_delete = "delete from exchange_table where name='" + exchane_name + "';";
            if (_sqliter.exec(sql_delete, nullptr, nullptr) == false)
            {
                INFO_LOG("删除交换机数据失败");
                return; // 退出程序
            }
        }
        // 查询交换机数据
        std::unordered_map<std::string, Exchange::ptr> getAllExchange()
        {
            // name - exchange来获取所以交换机数据
            std::unordered_map<std::string, Exchange::ptr> ret;
            std::string sql_select = "select name, type, durable, auto_delete, args from exchange_table";
            _sqliter.exec(sql_select, selectCallback, &ret); // 获取每一行交换机数据到ret中
            return ret;
        }

    private:
        static int selectCallback(void *args, int numcol, char **row, char **fields)
        {
            auto ret = (std::unordered_map<std::string, Exchange::ptr> *)args; // 获取一个交换机存储的哈希结构
            auto exchange = std::make_shared<Exchange>();                      // 获取一台交换机
            // 按顺序添加交换机数据到ret中
            exchange->_name = row[0];
            exchange->_type = (zhong::ExchangeType)std::stoi(row[1]);
            exchange->_durable = (bool)std::stoi(row[2]);
            exchange->_auto_delete = (bool)std::stoi(row[3]);
            if (row[4] != nullptr)
                exchange->setArgs(row[4]);

            ret->insert(std::make_pair(exchange->_name, exchange));
            return 0;
        }

    private:
        Sqliter _sqliter;
    };

    // 交换机数据内存管理类 --- 内存的交换机数据
    class ExchangeManager
    {
    public:
        using ptr = std::shared_ptr<ExchangeManager>;

        ExchangeManager(const std::string &data_base_file)
            : _mapper(data_base_file)
        {
            _exchanges = _mapper.getAllExchange();  // 通过=重载实现数据的拷贝
        }
        // 声明交换机
        bool declareExchange(const std::string &name,
                             ExchangeType type,
                             bool durable,
                             bool auto_delete,
                             const google::protobuf::Map<std::string, std::string> &args_map)
        { 
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _exchanges.find(name);
            if (it != _exchanges.end())
            {
                DEBUG_LOG("交换机[%s]已存在，不需要再次声明", name.c_str());
                return false; // 表示已经存在名称为name的交换机
            }
            // 创建并管理交换机
            auto exchange = std::make_shared<Exchange>(name, type, durable, auto_delete, args_map);
            if (exchange->_durable == true)
            {
                _mapper.insert(exchange); // 存储在磁盘中，也就是进行持久化存储
            }
            _exchanges.insert(std::make_pair(exchange->_name, exchange));
            return true;
        }
        // 删除交换机
        void deleteExchange(const std::string &name)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _exchanges.find(name);
            if (it == _exchanges.end())
            {
                return; // 不存在直接返回
            }
            if (it->second->_durable == true) // 持久化标志为true时，表示需要移除_mapper中的交换机
                _mapper.remove(name);
            
            _exchanges.erase(name);
        }
        // 获取指定交换机数据
        Exchange::ptr selectExchange(const std::string &name)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _exchanges.find(name);
            if (it == _exchanges.end())
            {
                return Exchange::ptr();
            }
            return it->second;
        }
        // 交换机是否存在
        bool exist(const std::string &name)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _exchanges.find(name);
            if (it == _exchanges.end())
            {
                return false;
            }
            return true;
        }
        size_t size()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return _exchanges.size();
        }
        // 清理所有交换机数据
        void clear()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _mapper.removeTable();
            _exchanges.clear();
        }

    private:
        std::mutex _mutex;
        ExchangeMapper _mapper;
        std::unordered_map<std::string, Exchange::ptr> _exchanges;
    };
};

#endif